<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns="http://www.w3.org/1999/xhtml">
  <head>
    <meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />
    <title>Logback Demo</title>
    <link rel="stylesheet" type="text/css" href="css/common.css" />
    <link rel="stylesheet" type="text/css" href="css/screen.css" media="screen" />
    <link rel="stylesheet" type="text/css" href="css/_print.css" media="print" />
  </head>
  <body>
    <script type="text/javascript">prefix=''; </script>

    <script src="templates/header.js" type="text/javascript"></script>
    <div id="left">
      <script src="templates/left.js" type="text/javascript"></script>
    </div>
    <div id="right">
      <script src="templates/right.js" type="text/javascript"></script>
    </div>

    <div id="content">
      
	
    <h2>Logback Demo</h2>

    <p>Welcome to the logback demo! This document will take you through
    a tour of some of logback's major features.
    </p>
    
    <h3>Installation</h3>

    <p> First, please download the logback demo. You will need to
    install a <a href="http://git-scm.com/">git</a>
    client and issue the following command on a console:
    </p>
  
    <p class="source">git clone git://github.com/qos-ch/logback-demo.git logback-demo</p>

    <p>This will retrieve a copy of the logback demonstration
    web-application to a directory called <em>logback-demo</em>. The
    logback demo can be packaged as a <em>war</em> file and deployed
    to an application server. We strongly recommend the use of <a
    href="http://maven.apache.org/">Maven</a> to accomplish this task,
    since it takes a single command in order to compile, package and
    run this demo.
    </p>

    <p>	Using Maven, let's package the files and run the demo for the first
    time.  From the <em>logback-demo</em> directory, issue the following
    command:
    </p>

    <div class="source"><pre>mvn package jetty:run</pre></div>
    
    <p>Then, visit <a
    href="http://localhost:8080/">http://localhost:8080/</a>
    to view the main page of the logback demo.
    </p>

    <h3>Logback-classic</h3>

    <p>By default (or as packaged), logback-demo configures
    logback-classic with two appenders: a <code>ConsoleAppender</code>
    and a <code>RollingFileAppender</code>. The
    <code>RollingFileAppender</code> sends logging events to a file
    called <em>logFile.log</em> and will rollover the active file
    every minute. The old file will be renamed and compressed to a
    <em>zip</em> file. The <code>ConsoleAppender</code> will output
    the logging requests to the console, and shorten the logger names
    to gain space on the console window, without loss of
    legibility. For example,
    <code>ch.qos.logback.demo.prime.NumberCruncherImpl </code> will be
    abbreviated as <code>c.q.l.d.prime.NumberCruncherImpl</code>.
    </p>

  <p>We highly encourage you to study the <em>logback.xml</em>
  configuration file located under the <em>src/main/resources/</em>
  folder. You might want to keep this file open in an editor window,
  since we will modify its contents throughout the demo.
  </p>

  <p>Let us now visit the <em>ViewStatii</em> page, via the navigation
  menu on the left hand side of your browser's window. This page
  contains the content of the <code>Status</code> objects that were
  created up until now. <code>Status</code> objects are a part of
  logback's internal reporting framework. They allow you to see what
  is going on inside logback, and check that a configuration file has
  been parsed correctly, or that rollovers occur as expected.
  </p>

  <p>You should be seeing log messages printed on the console and the
  contents of "logFile.log" file rolled over every minute.
  </p>

  <p>If you visit the <em>View logs</em> page (by clicking on the link
  located in the menu on the left), you should see it has no content. Let
  us change that by uncommenting <strong>two</strong> parts in the
  config file.</p>

  <p>Remove the comments around </p>

  <p class="source">&lt;!-- Basic Cyclic buffer
&lt;appender name="CYCLIC" class="ch.qos.logback.core.read.CyclicBufferAppender">
  &lt;MaxSize>512&lt;/MaxSize>
&lt;/appender>
--&gt;</p>
  <p>and around</p>

  <p class="source">&lt;!-- Part I: Basic Cyclic buffer
&lt;appender-ref ref="CYCLIC" />
--&gt;</p>

  <p>The <code>&lt;appender-ref></code> element found at the
  end of the configuration file links an appender to a given logger,
  in this particular case the root logger.
  </p>

  <p>A <code>CyclicBuffer</code> keeps track of the incoming logging event
  stream in a <a
  href="http://en.wikipedia.org/wiki/Circular_buffer">circular
  buffer</a> for later display. After having removed the comments
  around the two element/s shown above, reload the logback-demo
  web-application by exiting the previous "mvn" command with
  <em>CTRL-C</em> and issuing it again:
  </p>

  <p class="source">mvn package  jetty:run</p>

  <p>This time the <em>View logs</em> page should have contents.</p>

  <img src="images/cyclicView.png" alt="view logs"/>


  <p>By virtue of <code>CyclicBufferAppender</code>, this page can
  fetch the last events and present them through a servlet. We see
  that every ten seconds a line is added to the logs. The formatting
  of this page is made with a <code>HTMLLayout</code>. This component
  creates a table containing logging events, based on a pattern that
  describes the information you wish to see in the table.
  </p>

  <p>Having the logs cluttered with repetitive
  <em>Howdydy-diddly-ho</em> messages is wasteful. We can get rid of
  them with an appropriate filter. Uncomment the block entitled
  <em>Cyclic buffer with Evaluator</em>. You should then comment the
  block entitled "Basic Cyclic buffer" that we uncommented
  earlier.</p>

  <p>Let's take a look at the filter we've just added: </p>

<p class="source">&lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
  &lt;evaluator name="loggingTaskEval">
    &lt;expression>
      <b>logger.getName().contains("LoggingTask") &amp;amp;&amp;amp;
      message.contains("Howdydy-diddly-ho") &amp;amp;&amp;amp;
      (timeStamp - event.getStartTime()) >= 20000</b>
    &lt;/expression>
  &lt;/evaluator>
  &lt;OnMatch>DENY&lt;/OnMatch>
&lt;/filter></p>

  <p>The <code>&lt;expression></code> element uses the familiar
  Java language syntax. It checks that the name of the logger contains
  the String <em>LoggingTask</em>, but also that its message contains
  the string <em>Howdydy-diddly-ho</em>.  Moreover, in order to be
  sure that the <em>Howdydy-diddly-ho</em> task actually works, we add
  a last condition which checks that that at least 20 seconds have
  elapsed after application launch. The variable references in the
  expression, namely (<code>logger</code>, <code>message</code> and
  <code>event</code>) are implicitly made available by logback.  The
  <code>&lt;OnMatch></code> element lets the user specify the filter's
  behaviour once the expression matched (evaluated to true).
  </p>

  <p>After a restart, the <em>View logs</em> page will shows the
  <em>Howdydy-diddly-ho</em> logs, but only for the first 20
  seconds. If you wish to see new logging events to be shown on the
  "View logs" page, then visit the "Prime number" page.
  </p>

  <h4>Turbo Filters</h4>

  <p>Logback supports a special category of filters called
  TurboFilters.  <code>TurboFilter</code> objects are ultra-fast,
  context-wide filters. They can be very useful by setting
  context-wide (i.e. global) conditions for enabling or disabling
  logging events.
  </p>

  <p>Remove the comments around the block entitled "TurboFilter: MDC
  value".</p>

  <p class="source">&lt;turboFilter class="ch.qos.logback.classic.turbo.MDCFilter">
  &lt;MDCKey>username&lt;/MDCKey>
  &lt;Value>sebastien&lt;/Value>
  &lt;OnMatch>ACCEPT&lt;/OnMatch>
&lt;/turboFilter></p>


  <p>This <code>&lt;turboFilter></code> element adds a
  <code>TurboFilter</code> to the logging context which will enable
  events if the MDC contains a key named "username" set to the value
  "sebastien". The logback-demo application contains a <a
  href="http://java.sun.com/products/servlet/Filters.html">servlet
  filter</a> which will set the MDC key "username" with the name of
  the currently logged in user.</p>


  <p>For the purpose of this demo, let us disable all logging by
  setting the root logger's level to <code>OFF</code>.
  </p>

  <p class="source">&lt;root>
  &lt;level <b>value="OFF"</b>/>
  ...
&lt;/root></p>

  <p>Now restart the server as before.</p>

  <p>Once on the main demo webpage again, perform a number of actions
  (e.g. calculate a few prime numbers) and visit the <em>View
  logs</em> page. The table should be empty.
  </p>

  <p>Now login to the logback-demo web-application with the
  username <em>sebastien</em> and perform a few prime
  computations. The <em>View logs</em> page should show the logging
  events that were generated. Moreover, each logging event will have
  an MDC field associated with the name of the logged in user, in this
  case, sebastien. Please log off before continuing the demo, using
  the <em>logout</em> button on the left.
  </p>

 <img src="images/turboFilterForMDC.png" alt="mdc filters"/>

 <h4>Parameterized logging</h4>

 <p><a
 href="http://www.slf4j.org/faq.html#logging_performance">Parameterized
 logging </a> is not a logback feature per se. It is part of
 SLF4J. Usually, a logging request is issued as follows:
 </p>

<div class="source"><pre>logger.debug("Hello, my name is" + username + ", I am " + age + " years old.");</pre></div>

  <p>In the above call, the cost of constructing the message of type
  String is borne even if the log request is disabled. 
  </p>

  <p>SLF4J offers the following alternative:
  </p>

<div class="source"><pre>logger.debug("Hello, my name is {}, I am {} years old", username, age);</pre></div>

  <p>In this alternative, the final log message will be formatted only
  if the log statement is enabled.
  </p>

  <p>At present, let us see what kind of gain we can expect from this
  alternative approach. First, go to the <em>Prime number</em> page
  and compute factors for integers of your choice. Check the time it
  takes to compute the results. To see a clearer difference between
  the two formatting methods, you might want to try the two big
  integers that are listed below the prime number textbox. Jot down
  the time it takes to compute the result.
  </p>

  <p>Now let us edit the <code>NumberCruncherImpl</code> class in
  order to use parameterized logging.  You will find this class in the
  <em>src/main/java/ch/qos/logback/demo/prime/</em> directory. Comment
  line 54 (doing unconditional message concatenation) and uncomment
  line 55 (parameterized logging). Restart the server with <em>mvn
  package jetty:run</em> and re-run the factorization you tried
  beforehand.
  </p>

  <p>The time required to complete the computation should be much lower
  this time. Remember that we have turned off all logging in the
  previous step of this demo. In the initial version, we were
  constructing the message (<em>"Trying "+i+" as a factor."</em>) each
  time a factor was tested.  With the parameterized logging, the
  construction of the message was postponed and, since logging was
  turned off, never done. Thus, parameterized logging can
  significantly reduce the cost of disabled log statements.
  </p>

  <h4>Markers</h4>

  <p>You can color log statements with <em>markers</em>. Markers are
  part of the SLF4J API. If you look at the LoggingTask class (part of
  logback-demo) which includes the <em>Howdydy-diddly-ho</em> log
  statement, you should see that it is bound to a marker named
  <code>HOWDY</code> marker.  If you wish to drop log statements
  bearing the <code>HOWDY</code> marker, you can use this
  <code>TurboFilter</code> to do so:
  </p>

  <p class="source">&lt;turboFilter class="ch.qos.logback.classic.turbo.MarkerFilter">
    &lt;Name>HOWDY_FILTER&lt;/Name>
    &lt;Marker>HOWDY&lt;/Marker>
    &lt;OnMatch>DENY&lt;/OnMatch>
&lt;/turboFilter> </p>
  
  <p>After you have set the root logger's level back to <em>DEBUG</em>
  and uncommented the MarkerFilter block in <em>logback.xml</em>,
  restart the server.
  </p>


  <p>The logs bearing the <em>Howdydy-diddly-ho</em> message should no
  longer appear as they are associated with a HOWDY marker. You can check
  that by visiting the <em>View Logs</em> page.
  </p>

  <h2>Logback Access</h2>

  <p>Access logging is another important feature offered by
  logback. By default, the logback-demo web-application is configured
  so that each time you access it, an access log is printed on the
  console. The details of access logs are configured by the
  <em>logback-access.xml</em> file located under the <em>src/etc/</em>
  directory.
  </p>

  <p>Here is a rather minimal configuration for logback-access:</p>

<div class="source"><pre>&lt;configuration>
 
  &lt;appender name="STDOUT"
    class="ch.qos.logback.core.ConsoleAppender">
    &lt;layout class="ch.qos.logback.access.PatternLayout">
      &lt;Pattern>%h %l %u %t \"%r\" %s %b&lt;/Pattern>
    &lt;/layout>
  &lt;/appender>
  
  &lt;appender-ref ref="STDOUT" />
  
&lt;/configuration></pre></div>

  <p>Note that logback-classic and logback-access are configured via
  different files: <em>logback.xml</em> and
  <em>logback-access.xml</em> respectively. If you wanted to turn
  off logging for logback-classic by setting the level of the root
  logger to OFF, logback-access would be unaffected by this change.
  </p>

  <p>To see the logs produced by logback-access, just visit a few
  pages and look at your console. The information contained in each
  line has been specified in the configuration file. The
  <code>ConsoleAppender</code> named <em>STDOUT</em> contains a
  <code>PatternLayout</code> component.  This layout component is
  used in logback-classic to display either the message, logger name
  or level of the request, but in logback-access it is used to display the
  request method, requested page, status code and many other fields.
  </p>

<p>Here is a sample output for this appender.</p>

<div class="source"><pre>127.0.0.1 - - 22/Jan/2007:14:35:40 +0100 GET /logback-demo/ViewStatii.do HTTP/1.1 200 3660
127.0.0.1 - - 22/Jan/2007:14:35:41 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
127.0.0.1 - - 22/Jan/2007:14:35:42 +0100 GET /logback-demo/lastLog/ HTTP/1.1 200 948
127.0.0.1 - - 22/Jan/2007:14:35:42 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
127.0.0.1 - - 22/Jan/2007:14:35:43 +0100 GET /logback-demo/prime.jsp HTTP/1.1 200 1296
127.0.0.1 - - 22/Jan/2007:14:35:44 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
127.0.0.1 - - 22/Jan/2007:14:35:45 +0100 GET /logback-demo/lottery.jsp HTTP/1.1 200 1209
127.0.0.1 - - 22/Jan/2007:14:35:46 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
127.0.0.1 - - 22/Jan/2007:14:35:48 +0100 GET /logback-demo/reload.jsp HTTP/1.1 200 1335
127.0.0.1 - - 22/Jan/2007:14:35:49 +0100 GET /logback-demo/index.jsp HTTP/1.1 200 2389
127.0.0.1 - - 22/Jan/2007:14:35:54 +0100 GET /logback-demo/login.jsp HTTP/1.1 200 1214
127.0.0.1 - - 22/Jan/2007:14:35:55 +0100 GET /logback-demo/Logout.do HTTP/1.1 200 1000</pre></div>

  <h4>Filtering</h4>

  <p>In this next part, we are going to add some information to the
  console.  Let us imagine that we want to log the numbers that are
  tried on the <em>Lottery</em> page. We will need a second
  <code>ConsoleAppender</code> that will only print a given information
  (e.g. the guessed number, along with some hints about the player). The
  appender will also have to print that information only when a certain
  page is accessed.
  </p>

  <p>The necessary configuration lines are listed below.
  </p>

  <p class="source">&lt;appender name="STDOUT_LOTTERY"
  class="ch.qos.logback.core.ConsoleAppender">
  &lt;filter class="ch.qos.logback.core.filter.EvaluatorFilter">
    &lt;evaluator name="lotto_eval">
      &lt;Expression>
        url.matches(event.getRequestURL().toString())
      &lt;/Expression>
      &lt;matcher name="url">
        &lt;regex>Lottery.do&lt;/regex>
        &lt;caseSensitive>false&lt;/caseSensitive>
      &lt;/matcher>
    &lt;/evaluator>
    &lt;OnMatch>ACCEPT&lt;/OnMatch>
    &lt;OnMismatch>DENY&lt;/OnMismatch>
  &lt;/filter>
  &lt;layout class="ch.qos.logback.access.PatternLayout">
    &lt;Pattern>
      LOTTERY: %A [%r] Guess=%reqParameter{guessed_number}
    &lt;/Pattern>
  &lt;/layout>
&lt;/appender></p>

  <p>This appender will use a <code>PatternLayout</code> to format its
  output.  The <em>%reqParameter</em> conversion word is used to
  extract the guessed number from the request, and print it.
  </p>

  <p>It also uses an <code>EvaluatorFilter</code> that will prevent
  the appender to display anything when the access' request url does
  not match the given expression. You can see that it is easy to
  specify a RegExp, name it and use it in the expression that will be
  evaluated. In that case, we only entered the name of the
  <em>lottery.do</em> action.
  </p>

  <p>Let us uncomment the two elements with the <em>Lottery to
  Console</em> comments and restart the server. Now, try to play the
  lottery. You will see more lines in the Console that you've seen until
  now. At every try, logback will produce a log as shown below:
  </p>

  <p class="source">LOTTERY: 192.168.1.6 [POST /logback-demo/Lottery.do HTTP/1.1] Guess=321</p>

  <h4>Sending emails</h4>

  <p>Logback-access provides several components that are usually used
  by the classic module. For example, a <code>SMTPAppender</code> can
  be used to send an email when a specific event occurs. Here, we will
  contact the lottery administrator each time a winner is detected. To
  achieve this, we will add a <code>SMTPAppender</code> to the
  existing configuration. Please uncomment the part of
  <em>logback-access.xml</em> named <em>Lottery to Email</em>. Do not
  forget to uncomment the <em>appender-ref</em> element at the end of
  the configuration file that references the <em>SMTP</em> appender.
  In the appender element, notice the use of a
  <code>URLEvaluator</code>. This evaluator allows us to specify
  one or more URLs that are to be watched. When one of them is
  accessed, an email is sent.
  </p>

  <p>A reload of the configuration has to be done before we can test
  this new component. Once done, try to play the lottery with the
  number <em>99</em>.  You should see a "congratulation" message but,
  most importantly, the specified recipients should have a new mail in
  their mailbox. The content of the email is a nicely formatted HTML
  table with information about the accesses that occurred before
  the triggering event.
  </p>

  <h3>JMX</h3>

  <p>Logback publishes several components via JMX. This allows you to
  see the status of certain objects, and change several configuration
  parameters.  Publishing logback's components via JMX is possible
  with Jetty and Tomcat. For more information about the JMXConfigurator
  please refer to the <a href="manual/jmxConfig.html">relevant
  chapter</a> in the manual.
  </p>

  <p>Let us test setting levels using the configurator.
  The <em>Prime Number</em> page requests two types of logs. When the
  calculation checks if a number is a factor, a <em>DEBUG</em> log is
  displayed. When the calculation has found a factor, a <em>INFO</em>
  log is displayed.
  </p>

  <p>Let us first set the level of the logger named
  <em>ch.qos.logback.demo.prime</em> to <em>DEBUG</em>. Run a prime
  calculation directly, without restarting the server. The <em>View
  logs</em> page should show the <em>DEBUG</em> and <em>INFO</em> logs.
  </p>
  
  <p>Now, if you set the level of the <em>ch.qos.logback.demo.prime</em>
  logger to <em>INFO</em>, and run a prime calculation again, you should
  not see the <em>DEBUG</em> level logs anymore.
  </p>
  
  <p>This demo of logback is now over. Do not hesitate to play around
  with the configuration files.  You might want to check the <a
  href="http://logback.qos.ch/documentation.html"> logback documentation
  page</a> for more information about any component you'd like to test.
  </p>
	
  <script src="templates/footer.js" type="text/javascript"></script>
</div>
</body>
</html>
